﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using FastNET.CleanAct.Client.Win32.Unmanaged;
using System.Security.Principal;

namespace FastNET.CleanAct.Client.Win32
{
    public static class WindowsRegistry
    {

        public static bool LoadRegistry(String fileName, string subKeyName)
        {
            ElevateRights();

            return RegistryManipulation.RegLoadKey(RegistryManipulation.HKEY_USERS, subKeyName, fileName) == 0;
        }

        public static bool UnloadUserRegistry(string subKeyName)
        {
            ElevateRights();

            return RegistryManipulation.RegUnLoadKey(RegistryManipulation.HKEY_USERS, subKeyName) == 0;
        }

        private static void ElevateRights()
        {
            IntPtr token = IntPtr.Zero;

            RegistryManipulation.TOKEN_PRIVILEGES setTokenPrivileges = new RegistryManipulation.TOKEN_PRIVILEGES();
            RegistryManipulation.TOKEN_PRIVILEGES outTokenPrivileges = new RegistryManipulation.TOKEN_PRIVILEGES();
            int outTokenLength;

            if (!RegistryManipulation.OpenProcessToken(Process.GetCurrentProcess().Handle, TokenAccessLevels.AdjustPrivileges | TokenAccessLevels.Query, ref token))
            {
                throw new Win32Exception();
            }

            setTokenPrivileges.PrivilegeCount = 2;
            setTokenPrivileges.Privileges[2] = new RegistryManipulation.LUID_AND_ATRIBUTES();
            setTokenPrivileges.Privileges[0].Attributes = RegistryManipulation.SE_PRIVILEGE_ENABLED;
            setTokenPrivileges.Privileges[1].Attributes = RegistryManipulation.SE_PRIVILEGE_ENABLED;

            if (!RegistryManipulation.LookupPrivilegeValue(null, RegistryManipulation.SE_RESTORE_NAME, out setTokenPrivileges.Privileges[0].Luid))
            {
                throw new Win32Exception();
            }

            if (!RegistryManipulation.LookupPrivilegeValue(null, RegistryManipulation.SE_BACKUP_NAME, out setTokenPrivileges.Privileges[1].Luid))
            {
                throw new Win32Exception();
            }

            if (!RegistryManipulation.AdjustTokenPrivileges(token, false, setTokenPrivileges, Marshal.SizeOf(outTokenPrivileges), out outTokenPrivileges, out outTokenLength))
            {
                throw new Win32Exception();
            }
        }
    }
}
